package mqtt

import akka.actor.typed.ActorRef
import io.circe.generic.JsonCodec
import spray.json._

import java.sql.Timestamp

object EdgeDomain {

  sealed trait Sensor
  // Smoke detector - MQ2
  final case class MQ2(deviceId: String,
                       userId: String,
                       smokeConcentration: Double,
                       alarm: Boolean,
                       status: Boolean) extends Sensor

  // Temperature / Humidity detector - DHT11
  final case class DHT11(deviceId: String,
                         userId: String,
                         temperature: Double,
                         humidity: Double,
                         status: Boolean) extends Sensor

  // Atmospheric Pressure Detector - BMP280
  final case class BMP280(deviceId: String,
                          userId: String,
                          temperature: Double,
                          atmosphericPressure: Double,
                          altitude: Double,
                          status: Boolean) extends Sensor

  sealed trait Report
  final case class DHT11Report(service_id: String = "dht11",
                               properties: DHT11,
                               event_time: String) extends Report
  final case class MQ2Report(service_id: String = "mq2",
                             properties: MQ2,
                             event_time: String) extends Report
  final case class BMP280Report(service_id: String = "bmp280",
                                properties: BMP280,
                                event_time: String) extends Report

  @JsonCodec
  final case class Credential(device_domain: String, device_id: String, secret: String, user_id: String)

  // aggregator protocol
  trait AggregatorCommand
  final case class SensorRegister(deviceId: String,
                                  deviceDomain: String,
                                  deviceType: String,
                                  userId: String) extends AggregatorCommand
  final case class SensorReading(deviceId: String, sensorData: Sensor) extends AggregatorCommand
  final case class SensorReporting(deviceId: String, replyTo: ActorRef[Report]) extends AggregatorCommand
  final case class SensorUnregister(deviceId: String) extends AggregatorCommand

  // sensor command
  sealed trait SensorCommand
  final case object SensorHeartBeat extends SensorCommand
  final case object SensorShutDown extends SensorCommand
  final case class ChangeAggregator(newAggregator: Option[ActorRef[SensorReading]]) extends SensorCommand
}

trait EdgeDomainJsonProtocol extends DefaultJsonProtocol {

  import EdgeDomain._

  implicit val mq2JsonFormat: RootJsonFormat[MQ2] = jsonFormat5(MQ2)
  implicit val dht11JsonFormat: RootJsonFormat[DHT11] = jsonFormat5(DHT11)
  implicit val bmp280JsonFormat: RootJsonFormat[BMP280] = jsonFormat6(BMP280)

  implicit val dht11ReportJsonFormat: RootJsonFormat[DHT11Report] = jsonFormat3(DHT11Report)
  implicit val mq2ReportJsonFormat: RootJsonFormat[MQ2Report] = jsonFormat3(MQ2Report)
  implicit val bmp280ReportJsonFormat: RootJsonFormat[BMP280Report] = jsonFormat3(BMP280Report)
}
